﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace AdvancedScriptEditor
{
    public partial class FramelessScriptEditor : Form
    {
        #region Global Variables

        KeyEventArgs lastKeyPress = new KeyEventArgs(Keys.None);
        KeyEventArgs currentKeyPress = new KeyEventArgs(Keys.None);

        FunctionList functionList = new FunctionList();
        Options options = new Options();

        string[] args;
        string appPath;
        bool loaded = false;

        #endregion

        public FramelessScriptEditor()
        {
            InitializeComponent();
        }

        private void FramelessScriptEditor_Load(object sender, EventArgs e)
        {
            Properties.Settings.Default.AppPath = Application.StartupPath;
            appPath = Properties.Settings.Default.AppPath;
            args = Environment.GetCommandLineArgs();

            if (args.Length != 4)
            {
                MessageBox.Show("Error: One or more of the command-line parameters specified were incorrect.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Close();
            }

            string[] size = args[2].Split(',');
            int sizeX = int.Parse(size[0]);
            int sizeY = int.Parse(size[1]);
            this.ClientSize = new Size(sizeX, sizeY);

            string[] location = args[3].Split(',');
            int locX = int.Parse(location[0]);
            int locY = int.Parse(location[1]);
            this.Location = new Point(locX, locY);

            functionList.Load(appPath + "\\functions.txt", appPath + "\\descriptions.txt");
            functionTextBox.AutoCompleteCustomSource.AddRange(functionList.Functions);

            scriptEditor.AutoComplete.List.Clear();
            scriptEditor.AutoComplete.List.AddRange(functionList.Functions);
            scriptEditor.AutoComplete.List.Sort();

            string[] badfunctions = { "bool", "break", "case", "char", "double", "else", "false", "float", "for", "if", "int", "null", "Quaternion", "return", "string", "switch", "true", "Vector3", "void", "while" };
            string[] functions = new string[functionList.Functions.Length - badfunctions.Length];
            int count = 0;
            for (int i = 0; i < functionList.Functions.Length; i++)
            {
                bool goodFunction = true;
                for (int j = 0; j < badfunctions.Length; j++)
                {
                    if (functionList.Functions[i] == badfunctions[j])
                        goodFunction = false;
                }
                if (goodFunction)
                {
                    functions[count] = functionList.Functions[i];
                    count++;
                }
            }
            listBoxFunctions.Items.AddRange(functions);
            listBoxFavorites.Items.AddRange(File.ReadAllLines(appPath + "\\favorites.txt"));

            options.Load(appPath + "\\options.ini");

            UpdateDescriptionPane();
            loaded = true;
        }

        private void scriptEditor_KeyDown(object sender, KeyEventArgs e)
        {
            if (options.AutomaticallyShowAutocomplete == true)
            {
                if (e.KeyCode == Keys.Q ||
                    e.KeyCode == Keys.W ||
                    e.KeyCode == Keys.E ||
                    e.KeyCode == Keys.R ||
                    e.KeyCode == Keys.T ||
                    e.KeyCode == Keys.Y ||
                    e.KeyCode == Keys.U ||
                    e.KeyCode == Keys.I ||
                    e.KeyCode == Keys.O ||
                    e.KeyCode == Keys.P ||
                    e.KeyCode == Keys.A ||
                    e.KeyCode == Keys.S ||
                    e.KeyCode == Keys.D ||
                    e.KeyCode == Keys.F ||
                    e.KeyCode == Keys.G ||
                    e.KeyCode == Keys.H ||
                    e.KeyCode == Keys.J ||
                    e.KeyCode == Keys.K ||
                    e.KeyCode == Keys.L ||
                    e.KeyCode == Keys.Z ||
                    e.KeyCode == Keys.X ||
                    e.KeyCode == Keys.C ||
                    e.KeyCode == Keys.V ||
                    e.KeyCode == Keys.B ||
                    e.KeyCode == Keys.N ||
                    e.KeyCode == Keys.M)
                {
                    currentKeyPress = e;

                    int index = scriptEditor.Caret.Position;
                    int prevChar = -1;
                    if (index > 1) prevChar = scriptEditor.Text.IndexOf("\t", index - 1, 1);
                    if (prevChar != -1) scriptEditor.AutoComplete.Show();
                    lastKeyPress = e;
                }
            }
        }

        private void functionTextBox_TextChanged(object sender, EventArgs e)
        {
            UpdateDescriptionPane();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (scriptEditor.AutoComplete.IsActive)
            {
                string item = scriptEditor.AutoComplete.SelectedText;
                functionTextBox.Text = item;
                UpdateDescriptionPane();
            }
        }

        private void UpdateDescriptionPane()
        {
            int index = -1;
            for (int i = 0; i < functionList.Functions.Length; i++)
            {
                string fbFunc = functionList.Functions[i];
                string lbFunc = functionTextBox.Text.ToString();
                if (fbFunc == lbFunc)
                    index = i;
            }
            if (index != -1)
                rtbFunctionDescription.Text = functionList.Descriptions[index];
            else
                rtbFunctionDescription.Text = "No function description found.";
        }

        private void InsertText(string text, int selectionStart, int selectionEnd)
        {
            int pos = scriptEditor.Caret.Position;
            int index = scriptEditor.Caret.LineNumber;
            string lineText = scriptEditor.Lines[index].Text;
            string tabs = string.Empty;

            for (int i = 0; i < lineText.Length; i++)
                if (lineText[i] == '\t')
                    tabs = tabs + "\t";

            scriptEditor.InsertText(pos, text + "\n" + tabs + "{\n" + tabs + "}");
            scriptEditor.Selection.Start = pos + selectionStart;
            scriptEditor.Selection.Length = selectionEnd;
        }

        private void buttonFunctionsList_Click(object sender, EventArgs e)
        {
            splitContainerFunctions.Panel2Collapsed = !splitContainerFunctions.Panel2Collapsed;
        }

        #region Context Menu

        private void findFunctionDescriptionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            functionTextBox.Text = scriptEditor.Selection.Text;
            UpdateDescriptionPane();
        }

        private void functionEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FunctionEditor functionEditor = new FunctionEditor(functionList);
            functionEditor.ShowDialog();
            functionEditor.Dispose();
            functionList.Load(appPath + "\\functions.txt", appPath + "\\descriptions.txt");
            scriptEditor.AutoComplete.List.Clear();
            scriptEditor.AutoComplete.List.AddRange(functionList.Functions);
            scriptEditor.AutoComplete.List.Sort();
            UpdateDescriptionPane();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionsDialog optionsDialog = new OptionsDialog(options);
            optionsDialog.ShowDialog();
            optionsDialog.Dispose();
        }

        private void ifToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InsertText("if (condition)", 4, 9);
        }

        private void elseIfToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InsertText("else if (condition)", 9, 9);
        }

        private void elseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int pos = scriptEditor.Caret.Position;
            int index = scriptEditor.Caret.LineNumber;
            string lineText = scriptEditor.Lines[index].Text;
            string tabs = string.Empty;

            for (int i = 0; i < lineText.Length; i++)
                if (lineText[i] == '\t')
                    tabs = tabs + "\t";

            scriptEditor.InsertText(pos, "else\n" + tabs + "{\n" + tabs + "\t" + "\n" + tabs + "}");
            scriptEditor.Selection.Start = pos + 8 + (tabs.Length * 2);
        }

        private void forToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InsertText("for (condition; condition; condition)", 5, 9);
        }

        private void whileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InsertText("while (condition)", 7, 9);
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, "==");
        }

        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, "=>");
        }

        private void toolStripMenuItem5_Click(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, "=<");
        }

        private void toolStripMenuItem6_Click(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, ">");
        }

        private void toolStripMenuItem7_Click(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, "<");
        }

        #endregion

        private void btnGetScriptFrom3DRad_Click(object sender, EventArgs e)
        {
            scriptEditor.Text = File.ReadAllText(args[1]);
        }

        private void btnSaveScriptTo3DRad_Click(object sender, EventArgs e)
        {
            File.WriteAllText(args[1], scriptEditor.Text);
        }

        private void listBoxFunctions_DoubleClick(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, listBoxFunctions.SelectedItem.ToString());
        }

        private void listBoxFavorites_DoubleClick(object sender, EventArgs e)
        {
            scriptEditor.InsertText(scriptEditor.Caret.Position, listBoxFavorites.SelectedItem.ToString());
        }

        private void addToFavoritesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            listBoxFavorites.Items.Add(listBoxFunctions.SelectedItem.ToString());
            SaveFavorites();
        }

        private void removeFromFavoritesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            listBoxFavorites.Items.RemoveAt(listBoxFavorites.SelectedIndex);
            SaveFavorites();
        }

        private void SaveFavorites()
        {
            string[] favorites = new string[listBoxFavorites.Items.Count];
            for (int i = 0; i < listBoxFavorites.Items.Count; i++)
                favorites[i] = listBoxFavorites.Items[i].ToString();
            File.WriteAllLines(appPath + "\\favorites.txt", favorites);
        }

        private void listBoxFunctions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxFunctions.SelectedIndices.Count > 0)
            {
                functionTextBox.Text = listBoxFunctions.SelectedItem.ToString();
                UpdateDescriptionPane();
            }
        }

        private void listBoxFavorites_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxFavorites.SelectedIndices.Count > 0)
            {
                functionTextBox.Text = listBoxFavorites.SelectedItem.ToString();
                UpdateDescriptionPane();
            }
        }

        private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Sorry, but the help file is incomplete. It will be updated in the next release.", "Help", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (AboutBox aboutBox = new AboutBox())
            { aboutBox.ShowDialog(); }
        }

        private void checkForUpdatesToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Sorry, but the updater is incomplete. It will be updated in the next release.", "Help", MessageBoxButtons.OK, MessageBoxIcon.Information);

            /*
            string[] batchFile =
            {
                string.Format("copy {0}\\FramelessScriptEditorTemp.exe {0}\\FramelessScriptEditor.exe", appPath),
                string.Format("del {0}\\FramelessScriptEditorTemp.exe", appPath),
            };
            */
        }
    }
}
